home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Deutsche Edition 1
/
Deutsche Edition 1.iso
/
amok
/
amok_lha
/
amok44.lha
/
Analyse3.01
/
analyse.mod
< prev
next >
Wrap
Text File
|
1993-08-15
|
38KB
|
1,067 lines
(* $f- $n- $r- $s- $v- *)
(************************************)
(* *)
(* analyse V 3.01 22-aug-1989 *)
(* *)
(* (C) by Lothar Schwab *)
(* created by Lothar Schwab *)
(* *)
(************************************)
IMPLEMENTATION MODULE analyse;
FROM SYSTEM IMPORT FFP , ADR , ADDRESS;
FROM Exec IMPORT WaitPort , GetMsg , PutMsg ,
Message , MsgPortPtr , MemReqs ,
MemReqSet , AllocMem , FreeMem;
FROM Dos IMPORT LoadSeg , UnLoadSeg , CreateProc ,
ProcessId;
FROM Arts IMPORT Assert , TermProcedure;
FROM ExecSupport IMPORT CreatePort , DeletePort;
FROM FFPConversions IMPORT RealToStr;
FROM Conversions IMPORT ValToStr;
FROM MathTrans IMPORT Sin , Cos , Tan , Asin , Acos , Atan ,
Sinh , Cosh , Tanh , Exp , Log , Pow ,
Log10 , Sqrt;
FROM Str IMPORT CopyPos;
CONST pizahl = 3.1415926536;
pihalbe = 1.5707963268;
ezahl = 2.7182818284;
lnzehn = 2.3025850930;
max = 1.0E18;
mmax = -1.0E18;
lnmax = 41.4465;
fnamenlaenge = 7;
endezeichen = CHAR (0);
blank = ' ';
TYPE knotentypen = (
operationsknoten , funktionsknoten ,
reellzahlknoten , ganzzahlknoten ,
variablenknoten
);
verknuepfungen = ( plus , minus , mal , durch , hoch );
funktionen = (
sinush , cosinush , tangensh , cotangensh ,
arsinush , arcosinush , artangensh , arcotangensh ,
sinus , cosinus , tangens , cotangens ,
arcsinus , arccosinus , arctangens , arccotangens ,
ehoch , lne , lg , pot10 ,
wurzel , quadrat , ende
);
jobtypen = (
jobfunktion , jobcodegen ,
jobcodeloe , jobcodeanf ,
jobkill
);
knotenzeiger = POINTER TO knoten;
knoten = RECORD
links , rechts : knotenzeiger;
invers : BOOLEAN;
CASE typ : knotentypen OF
operationsknoten : operation : verknuepfungen
| funktionsknoten : funktion : funktionen
| reellzahlknoten : reellzahl : FFP
| ganzzahlknoten : ganzzahl : INTEGER
| variablenknoten : variable : CHAR
END (* CASE *)
END (* RECORD *);
lkopftyp = ARRAY knotentypen OF knotenzeiger;
string = ARRAY [1 .. fnamenlaenge] OF CHAR;
startupmsgtyp = RECORD
startupkopf : Message;
kportadr : ADDRESS;
errorflg : CHAR
END;
kommandomsgtyp = RECORD
kommandokopf : Message;
knotenadr : knotenzeiger;
xwert : FFP;
ywert : FFP;
zwert : FFP;
codeadr : ADDRESS;
job : jobtypen;
fehlerflg : CHAR;
ergebniss : FFP
END;
VAR fnamen : ARRAY [sinush .. ende ] OF string;
serverseg : ADDRESS;
serverproc : ProcessId;
replyportptr : MsgPortPtr;
startupmsg : startupmsgtyp;
kommandomsg : kommandomsgtyp;
dummy : ADDRESS;
kommandoport : MsgPortPtr;
PROCEDURE macheknoten ( VAR baum : knotenzeiger ; art : knotentypen );
BEGIN
baum := AllocMem ( SIZE ( knoten ) , MemReqSet { memClear } );
baum^.typ := art;
baum^.links := NIL;
baum^.rechts := NIL
END macheknoten;
PROCEDURE shootdownserver;
BEGIN
kommandomsg.job := jobkill;
PutMsg ( kommandoport , ADR ( kommandomsg ) );
WaitPort ( replyportptr );
dummy := GetMsg ( replyportptr );
UnLoadSeg ( serverseg );
DeletePort ( replyportptr )
END shootdownserver;
PROCEDURE optimiere ( VAR baum : knotenzeiger ); FORWARD;
PROCEDURE infix ( VAR string : ARRAY OF CHAR ; baum : knotenzeiger );
TYPE wannklammern = SET OF verknuepfungen;
VAR i , j , max : CARDINAL;
feld : ARRAY [1 .. 20] OF CHAR;
negklammer : BOOLEAN;
PROCEDURE infix2 ( baum : knotenzeiger ); FORWARD;
PROCEDURE klammerbaum ( baum : knotenzeiger );
BEGIN
IF i < max THEN
string [i] := '(';
INC ( i );
infix2 ( baum );
IF i < max THEN
string [i] := ')';
INC ( i )
ELSE ok := FALSE
END (* IF *)
ELSE ok := FALSE
END (* IF *)
END klammerbaum;
PROCEDURE opbaum ( baum : knotenzeiger ; klammerops : wannklammern );
VAR re , li : knotenzeiger;
BEGIN
re := baum^.rechts;
li := baum^.links;
IF ( li^.typ = operationsknoten ) AND
( li^.operation IN klammerops ) THEN
klammerbaum ( li )
ELSE
infix2 ( li )
END (* IF *);
IF ok AND ( i < max ) THEN
CASE baum^.operation OF
plus : string [i] := '+'
| minus : string [i] := '-'
| mal : string [i] := '*'
| durch : string [i] := '/'
| hoch : string [i] := '^'
END (* CASE *);
INC ( i );
IF ( re^.typ = operationsknoten ) AND
( re^.operation IN klammerops ) THEN
klammerbaum ( re )
ELSE
infix2 ( re )
END (* IF *)
ELSE ok := FALSE
END (* IF *)
END opbaum;
PROCEDURE infix2 ( baum : knotenzeiger );
BEGIN (* von infix2 *)
IF ( baum # NIL ) AND ok THEN
IF i < max THEN
CASE baum^.typ OF
operationsknoten :
CASE baum^.operation OF
plus , minus :
opbaum ( baum , wannklammern { } )
| mal , durch :
opbaum ( baum , wannklammern { plus , minus } )
| hoch :
opbaum ( baum , wannklammern { plus , minus , mal , durch } )
END (* CASE *)
| funktionsknoten :
IF ( max - i ) < fnamenlaenge THEN
ok := FALSE
ELSE
j := 1;
REPEAT
string [i] := fnamen [baum^.funktion , j];
INC ( i );
INC ( j )
UNTIL fnamen [baum^.funktion , j] = blank;
klammerbaum ( baum^.links )
END (* IF *)
| variablenknoten :
CASE baum^.variable OF
CHAR ( 255 ) :
string [i] := 'Z';
INC ( i );
|CHAR ( 254 ) :
string [i] := 'Y';
INC ( i );
|CHAR ( 253 ) :
string [i] := 'X';
INC ( i );
ELSE
IF i > ( max - 4 ) THEN
ok := FALSE
ELSE
ValToStr ( LONGINT ( baum^.variable ) , FALSE , feld , 10 ,
3 , '0' , ok );
ok := NOT ( ok );
IF ok THEN
string [i] := 'X';
INC ( i );
CopyPos ( string , feld , i );
INC ( i , 3 );
END (* IF *)
END (* IF *)
END (* CASE *)
| reellzahlknoten :
RealToStr ( baum^.reellzahl , feld , -15 , 2 , FALSE , ok );
j := 1;
ok := TRUE;
negklammer := baum^.reellzahl < 0.;
IF negklammer THEN
IF i < max THEN
string [i] := '(';
INC ( i )
ELSE
ok := FALSE
END (* IF *)
END (* IF *);
WHILE ( i < max ) AND ( feld [j] # blank ) AND ( j <= 15 ) DO
string [i] := feld [j];
INC ( i );
INC ( j )
END (* WHILE *);
IF ( i >= max ) OR ( feld [j] # blank ) THEN
ok := FALSE
ELSE
IF negklammer THEN
string [i] := ')';
INC ( i )
END (* IF *)
END (* IF *)
| ganzzahlknoten :
ValToStr ( baum^.ganzzahl , TRUE , feld , 10 , -10 , ' ' , ok );
j := 1;
ok := TRUE;
negklammer := baum^.ganzzahl < 0;
IF negklammer THEN
IF i < max THEN
string [i] := '(';
INC ( i )
ELSE
ok := FALSE
END (* IF *)
END (* IF *);
WHILE ( i < max ) AND ( feld [j] # blank ) AND ( j <= 10 ) DO
string [i] := feld [j];
INC ( i );
INC ( j )
END (* WHILE *);
IF i >= max THEN
ok := FALSE
ELSE
IF negklammer THEN
string [i] := ')';
INC ( i )
END (* IF *)
END (* IF *)
END (* CASE *)
ELSE ok := FALSE
END (* IF *)
END (* IF *)
END infix2;
BEGIN (* von infix *)
ok := TRUE;
i := 0;
max := HIGH ( string );
infix2 ( baum );
IF ok THEN
string [i] := 0C
END (* IF *)
END infix;
PROCEDURE ableitung ( VAR f , fstrich : knotenzeiger ; variable : CHAR );
PROCEDURE kopierebaum ( quelle : knotenzeiger ; VAR ziel : knotenzeiger );
BEGIN (* von kopierebaum *)
IF quelle # NIL THEN
ziel := AllocMem ( SIZE ( knoten ) , MemReqSet {} );
ziel^ := quelle^;
kopierebaum ( quelle^.rechts , ziel^.rechts );
kopierebaum ( quelle^.links , ziel^.links )
ELSE ziel := NIL
END (* IF *)
END kopierebaum;
PROCEDURE ableitung2 ( VAR baum : knotenzeiger );
VAR hilf , hilfl , hilfr : knotenzeiger;
PROCEDURE negativ ( zeiger : knotenzeiger ) : knotenzeiger;
VAR hilf : knotenzeiger;
BEGIN
macheknoten ( hilf , operationsknoten );
hilf^.operation := mal;
hilf^.rechts := zeiger;
macheknoten ( hilf^.links , ganzzahlknoten );
hilf^.links^.ganzzahl := -1;
RETURN ( hilf )
END negativ;
PROCEDURE wrzl ( zeiger : knotenzeiger ) : knotenzeiger;
VAR hilf : knotenzeiger;
BEGIN
macheknoten ( hilf , funktionsknoten );
hilf^.funktion := wurzel;
hilf^.links := zeiger;
RETURN ( hilf )
END wrzl;
PROCEDURE reziprok ( zeiger : knotenzeiger ) : knotenzeiger;
VAR hilf : knotenzeiger;
BEGIN
macheknoten ( hilf , operationsknoten );
hilf^.operation := durch;
hilf^.rechts := zeiger;
macheknoten ( hilf^.links , ganzzahlknoten );
hilf^.links^.ganzzahl := 1;
RETURN ( hilf )
END reziprok;
BEGIN (* von ableitung2 *)
IF baum # NIL THEN
CASE baum^.typ OF
operationsknoten:
CASE baum^.operation OF
plus , minus :
ableitung2 ( baum^.links );
ableitung2 ( baum^.rechts )
| mal :
kopierebaum ( baum^.links , hilfl );
kopierebaum ( baum^.rechts , hilfr );
ableitung2 ( hilfl );
ableitung2 ( hilfr );
macheknoten ( hilf , operationsknoten );
hilf^.operation := mal;
hilf^.links := hilfl;
hilf^.rechts := baum^.rechts;
baum^.rechts := hilfr;
macheknoten ( hilfl , operationsknoten );
hilfl^.operation := plus;
hilfl^.links := hilf;
hilfl^.rechts := baum;
baum := hilfl
| durch :
kopierebaum ( baum^.rechts , hilf );
baum^.operation := mal;
ableitung2 ( baum );
baum^.operation := minus;
macheknoten ( hilfl , funktionsknoten );
hilfl^.funktion := quadrat;
hilfl^.links := hilf;
macheknoten ( hilf , operationsknoten );
hilf^.operation := durch;
hilf^.links := baum;
hilf^.rechts := hilfl;
baum := hilf
| hoch :
kopierebaum ( baum , hilf );
baum^.operation := mal;
macheknoten ( hilfl , funktionsknoten );
hilfl^.funktion := lne;
hilfl^.links := baum^.links;
baum^.links := hilfl;
ableitung2 ( baum );
macheknoten ( hilfl , operationsknoten );
hilfl^.operation := mal;
hilfl^.links := hilf;
hilfl^.rechts := baum;
baum := hilfl
END (* CASE *)
| funktionsknoten :
kopierebaum ( baum^.links , hilf );
CASE baum^.funktion OF
sinush :
baum^.funktion := cosinush
| cosinush :
baum^.funktion := sinush
| tangensh :
baum := wrzl ( baum );
baum^.funktion := quadrat;
baum := reziprok ( baum );
baum^.operation := minus
| cotangensh :
baum := wrzl ( baum );
baum^.funktion := quadrat;
baum := reziprok ( baum );
baum^.operation := minus
| arsinush :
baum^.funktion := quadrat;
baum := reziprok ( baum );
baum^.operation := plus;
baum := wrzl ( baum );
baum := reziprok ( baum )
| arcosinush :
baum^.funktion := quadrat;
baum := negativ ( baum );
baum^.operation := plus;
baum := wrzl ( baum );
baum := reziprok ( baum )
| artangensh :
baum^.funktion := quadrat;
baum := reziprok ( baum );
baum^.operation := minus;
baum := reziprok ( baum )
| arcotangensh :
baum^.funktion := quadrat;
baum := reziprok ( baum );
baum^.operation := minus;
baum := reziprok ( baum )
| sinus :
baum^.funktion := cosinus
| cosinus :
baum^.funktion := sinus;
baum := negativ ( baum )
| tangens :
baum := wrzl ( baum );
baum^.funktion := quadrat;
baum := reziprok ( baum );
baum^.operation := plus
| cotangens :
baum := wrzl ( baum );
baum^.funktion := quadrat;
baum := negativ ( baum );
baum^.operation := minus
| arcsinus :
baum^.funktion := quadrat;
baum := reziprok ( baum );
baum^.operation := minus;
baum := wrzl ( baum );
baum := reziprok ( baum )
| arccosinus :
baum^.funktion := quadrat;
baum := reziprok ( baum );
baum^.operation := minus;
baum := wrzl ( baum );
baum := reziprok ( baum );
baum := negativ ( baum )
| arctangens :
baum^.funktion := quadrat;
baum := reziprok ( baum );
baum^.operation := plus;
baum := reziprok ( baum )
| arccotangens :
baum^.funktion := quadrat;
baum := reziprok ( baum );
baum^.operation := plus;
baum := reziprok ( baum );
baum := negativ ( baum )
| ehoch :
| lne :
hilfl := baum;
baum := baum^.links;
FreeMem ( hilfl , SIZE ( knoten ) );
baum := reziprok ( baum )
| lg :
hilfl := baum;
baum := baum^.links;
FreeMem ( hilfl , SIZE ( knoten ) );
baum := reziprok ( baum );
baum := reziprok ( baum );
hilfl := baum^.links;
baum^.links := baum^.rechts;
baum^.rechts := hilfl;
hilfl^.typ := reellzahlknoten;
hilfl^.reellzahl := lnzehn
| pot10 :
baum := negativ ( baum );
baum^.links^.typ := reellzahlknoten;
baum^.links^.reellzahl := lnzehn
| wurzel :
baum := negativ ( baum );
baum^.links^.ganzzahl := 2;
baum := reziprok ( baum )
| quadrat :
baum^.typ := operationsknoten;
baum^.operation := mal;
macheknoten ( baum^.rechts , ganzzahlknoten );
baum^.rechts^.ganzzahl := 2
END (* CASE *);
ableitung2 ( hilf );
macheknoten ( hilfl , operationsknoten );
hilfl^.operation := mal;
hilfl^.links := baum;
hilfl^.rechts := hilf;
baum := hilfl
| reellzahlknoten :
baum^.typ := ganzzahlknoten;
baum^.ganzzahl := 0
| ganzzahlknoten :
baum^.ganzzahl := 0
| variablenknoten :
IF variable = baum^.variable THEN
baum^.typ := ganzzahlknoten;
baum^.ganzzahl := 1
ELSE
baum^.typ := ganzzahlknoten;
baum^.ganzzahl := 0
END (* IF *)
END (* CASE *)
END (* IF *)
END ableitung2;
BEGIN (* von ableitung *)
ok := TRUE;
kopierebaum ( f , fstrich );
ableitung2 ( fstrich );
optimiere ( fstrich )
END ableitung;
PROCEDURE codeanf ( VAR operationen : ADDRESS );
BEGIN
kommandomsg.job := jobcodeanf;
PutMsg ( kommandoport , ADR ( kommandomsg ) );
WaitPort ( replyportptr );
dummy := GetMsg ( replyportptr );
operationen := kommandomsg.codeadr;
ok := kommandomsg.fehlerflg = CHAR ( 0 )
END codeanf;
PROCEDURE codeloe ( VAR operationen : ADDRESS );
BEGIN
kommandomsg.job := jobcodeloe;
kommandomsg.codeadr := operationen;
PutMsg ( kommandoport , ADR ( kommandomsg ) );
WaitPort ( replyportptr );
dummy := GetMsg ( replyportptr )
END codeloe;
PROCEDURE codegen ( operationen : ADDRESS ; VAR baum : knotenzeiger );
BEGIN (* von codegen *)
kommandomsg.job := jobcodegen;
kommandomsg.codeadr := operationen;
kommandomsg.knotenadr := baum;
PutMsg ( kommandoport , ADR ( kommandomsg ) );
WaitPort ( replyportptr );
dummy := GetMsg ( replyportptr );
ok := kommandomsg.fehlerflg = CHAR ( 0 );
baum := kommandomsg.knotenadr
END codegen;
PROCEDURE funktion ( operationen : ADDRESS ) : FFP;
BEGIN
kommandomsg.job := jobfunktion;
kommandomsg.codeadr := operationen;
kommandomsg.xwert := x;
kommandomsg.ywert := y;
kommandomsg.zwert := z;
PutMsg ( kommandoport , ADR ( kommandomsg ) );
WaitPort ( replyportptr );
dummy := GetMsg ( replyportptr );
ok := kommandomsg.fehlerflg = CHAR ( 0 );
RETURN ( kommandomsg.ergebniss )
END funktion;
PROCEDURE parser ( VAR eingabe : ARRAY OF CHAR ; VAR baum : knotenzeiger );
VAR altpos : INTEGER;
PROCEDURE azeichen () : CHAR;
BEGIN
RETURN ( eingabe [position] )
END azeichen;
PROCEDURE nzeichen ();
BEGIN
altpos := position + 1;
REPEAT
INC ( position )
UNTIL eingabe [position] # blank
END nzeichen;
PROCEDURE summand ( VAR baum : knotenzeiger ); FORWARD;
PROCEDURE faktor ( VAR baum : knotenzeiger ); FORWARD;
PROCEDURE basisexponent ( VAR baum : knotenzeiger ); FORWARD;
PROCEDURE funktion ( VAR baum : knotenzeiger ); FORWARD;
PROCEDURE holezahl ( VAR baum : knotenzeiger );
VAR vorkomma : INTEGER;
wert , schieber : FFP;
BEGIN
macheknoten ( baum , ganzzahlknoten );
vorkomma := 0;
REPEAT
vorkomma := vorkomma * 10;
vorkomma := vorkomma + ORD ( azeichen () ) - ORD ( '0' );
nzeichen
UNTIL ( azeichen () < '0' ) OR ( azeichen () > '9' );
IF azeichen () <> '.' THEN
baum^.ganzzahl := vorkomma
ELSE
nzeichen;
baum^.typ := reellzahlknoten;
schieber := 1.0;
wert := 0.0;
WHILE ( azeichen () <= '9' ) AND ( azeichen () >= '0' ) DO
schieber := schieber / 10.;
wert := wert + FFP ( ORD ( azeichen () ) - ORD ('0') ) *
schieber;
nzeichen
END (* WHILE *);
baum^.reellzahl := FFP ( vorkomma ) + wert
END (* IF *)
END holezahl;
PROCEDURE ausdruck ( VAR baum : knotenzeiger );
VAR hilf : knotenzeiger;
zeichen : CHAR;
weiter : BOOLEAN;
BEGIN
zeichen := azeichen ();
IF zeichen = '-' THEN
nzeichen;
macheknoten ( baum , operationsknoten );
baum^.operation := mal;
macheknoten ( baum^.links , ganzzahlknoten );
baum^.links^.ganzzahl := -1;
summand ( baum^.rechts )
ELSE
IF zeichen = '+' THEN
nzeichen
END (* IF *);
summand ( baum )
END (* IF *);
weiter := TRUE;
WHILE ok AND weiter DO
zeichen := azeichen ();
IF ( zeichen = '+' ) OR ( zeichen = '-' ) THEN
nzeichen;
macheknoten ( hilf , operationsknoten );
IF zeichen = '+' THEN
hilf^.operation := plus
ELSE
hilf^.operation := minus
END (* IF *);
hilf^.links := baum;
baum := hilf;
summand ( baum^.rechts );
ELSE
weiter := FALSE
END (* IF *)
END (* WHILE *)
END ausdruck;
PROCEDURE summand ( VAR baum : knotenzeiger );
VAR hilf : knotenzeiger;
weiter : BOOLEAN;
zeichen : CHAR;
BEGIN
faktor ( baum );
weiter := TRUE;
WHILE ok AND weiter DO
zeichen := azeichen ();
IF ( zeichen = '*' ) OR ( zeichen = '/' ) THEN
nzeichen;
macheknoten ( hilf , operationsknoten );
IF zeichen = '*' THEN
hilf^.operation := mal
ELSE
hilf^.operation := durch
END (* IF *);
hilf^.links := baum;
baum := hilf;
faktor ( baum^.rechts )
ELSE
weiter := FALSE
END (* IF *)
END (* WHILE *)
END summand;
PROCEDURE faktor ( VAR baum : knotenzeiger );
VAR hilf : knotenzeiger;
BEGIN
basisexponent ( baum );
IF ok AND ( azeichen () = '^' ) THEN
nzeichen;
macheknoten ( hilf , operationsknoten );
hilf^.operation := hoch;
hilf^.links := baum;
baum := hilf;
basisexponent ( baum^.rechts )
END (* IF *)
END faktor;
PROCEDURE basisexponent ( VAR baum : knotenzeiger );
VAR zeichen : CHAR;
index : INTEGER;
BEGIN
zeichen := azeichen ();
CASE zeichen OF
'0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' :
holezahl ( baum )
| 'P' :
IF eingabe [position + 1] = 'I' THEN
nzeichen;
nzeichen;
macheknoten ( baum , reellzahlknoten );
baum^.reellzahl := pizahl
ELSE
funktion ( baum )
END (* IF *)
| 'E' :
IF eingabe [position + 1] = 'U' THEN
nzeichen;
nzeichen;
macheknoten ( baum , reellzahlknoten );
baum^.reellzahl := ezahl
ELSE
funktion ( baum )
END (* IF *)
| 'X' , 'Y' , 'Z' :
nzeichen;
macheknoten ( baum , variablenknoten );
CASE zeichen OF
'X' :
zeichen := azeichen ();
IF ( zeichen >= '0' ) AND ( zeichen <= '9' ) THEN
index := 0;
REPEAT
index := index * 10;
index := index + ORD ( azeichen () ) - ORD ( '0' );
nzeichen
UNTIL ( azeichen () < '0' ) OR ( azeichen () > '9' );
IF ( index > varanzahl ) THEN
ok := FALSE;
fehler := falscherindex
ELSE
abhfeld [index] := TRUE;
IF ( index > maxvar ) THEN
maxvar := index
END (* IF *);
baum^.variable := CHAR ( index )
END (* IF *)
ELSE
xabh := TRUE;
baum^.variable := CHAR ( 253 )
END (* IF *)
| 'Y' :
yabh := TRUE;
baum^.variable := CHAR ( 254 );
| 'Z' :
zabh := TRUE;
baum^.variable := CHAR ( 255 );
END (* CASE *);
| '(' :
nzeichen;
ausdruck ( baum );
IF ok THEN
IF azeichen () = ')' THEN
nzeichen
ELSE
ok := FALSE;
fehler := klammerzuerwartet
END (* IF *)
END (* IF *)
ELSE (* OTHERWISE *)
funktion ( baum )
END (* CASE *)
END basisexponent;
PROCEDURE funktion ( VAR baum : knotenzeiger );
VAR fgefunden : BOOLEAN;
gleich : BOOLEAN;
weiter : BOOLEAN;
i : funktionen;
j : INTEGER;
BEGIN
fgefunden := FALSE;
i := sinush;
REPEAT
j := 0;
gleich := TRUE;
REPEAT
gleich := eingabe [position + j] = fnamen [i , j + 1];
INC ( j );
UNTIL NOT ( gleich ) OR ( fnamen [i , j + 1] = blank );
IF gleich THEN
fgefunden := TRUE;
position := position + j
ELSE
INC ( i )
END (* IF *)
UNTIL fgefunden OR ( i = ende );
IF i = ende THEN
ok := FALSE;
fehler := quatsch
ELSE
IF azeichen () = blank THEN
nzeichen
END (* IF *);
IF azeichen () = '(' THEN
nzeichen;
macheknoten ( baum , funktionsknoten );
baum^.funktion := i;
ausdruck ( baum^.links );
IF ok THEN
IF azeichen () = ')' THEN
nzeichen;
ELSE
ok := FALSE;
fehler := klammerzuerwartet
END (* IF *)
END (* IF *)
ELSE
ok := FALSE;
fehler := klammerauferwartet
END (* IF *)
END (* IF *)
END funktion;
BEGIN (* von parser *)
FOR position := 1 TO varanzahl DO
abhfeld [position] := FALSE
END (* FOR *);
FOR position := 0 TO HIGH ( eingabe ) DO
eingabe [position] := CAP ( eingabe [position] )
END (* FOR *);
maxvar := -1;
position := -1;
altpos := -1;
baum := NIL;
xabh := FALSE;
yabh := FALSE;
zabh := FALSE;
ok := TRUE;
nzeichen ( );
ausdruck ( baum );
IF ok AND NOT ( eingabe [position] = endezeichen ) THEN
ok := FALSE;
fehler := woistdastermende
END (* IF *);
IF ok THEN
optimiere ( baum );
END (* IF *);
position := altpos
END parser;
PROCEDURE loesche ( VAR baum : knotenzeiger );
BEGIN
IF baum # NIL THEN
loesche ( baum^.links );
loesche ( baum^.rechts );
FreeMem ( baum , SIZE ( knoten ) );
baum := NIL
END (* IF *)
END loesche;
PROCEDURE optimiere ( VAR baum : knotenzeiger );
VAR optcode : ADDRESS;
PROCEDURE loeschelinks ( baum : knotenzeiger ) : knotenzeiger;
VAR helfer : knotenzeiger;
BEGIN (* von loeschelinks *)
helfer := baum^.rechts;
loesche ( baum^.links );
FreeMem ( baum , SIZE ( knoten ) );
RETURN ( helfer )
END loeschelinks;
PROCEDURE loescherechts ( baum : knotenzeiger ) : knotenzeiger;
VAR helfer : knotenzeiger;
BEGIN (* von loescherechts *)
helfer := baum^.links;
loesche ( baum^.rechts );
FreeMem ( baum , SIZE ( knoten ) );
RETURN ( helfer )
END loescherechts;
PROCEDURE optimiere2 ( VAR baum : knotenzeiger );
VAR lizgr , rezgr : knotenzeiger;
PROCEDURE konstausdruck ( VAR baum : knotenzeiger );
VAR lizgr , rezgr : knotenzeiger;
wert : FFP;
ganzzahlig : BOOLEAN;
BEGIN
lizgr := baum^.links;
rezgr := baum^.rechts;
IF baum^.typ = operationsknoten THEN
IF ( lizgr^.typ = ganzzahlknoten ) OR
( lizgr^.typ = reellzahlknoten ) THEN
IF ( rezgr^.typ = ganzzahlknoten ) OR
( rezgr^.typ = reellzahlknoten ) THEN
ganzzahlig := ( rezgr^.typ = ganzzahlknoten );
IF ( baum^.operation = durch ) OR
( lizgr^.typ = reellzahlknoten ) THEN
ganzzahlig := FALSE
END;
codegen ( optcode , baum );
wert := funktion ( optcode );
IF ok THEN
baum := loescherechts ( baum );
IF ganzzahlig AND ( ABS ( wert ) < 32000. ) THEN
baum^.typ := ganzzahlknoten;
IF wert > 0. THEN
baum^.ganzzahl := TRUNC ( wert + 0.5 )
ELSE
baum^.ganzzahl := TRUNC ( wert - 0.5 )
END (* IF *)
ELSE
baum^.typ := reellzahlknoten;
baum^.reellzahl := wert
END (* IF *)
END (* IF *)
END (* IF *)
END (* IF *)
ELSIF baum^.typ = funktionsknoten THEN
IF ( lizgr^.typ = ganzzahlknoten ) OR
( lizgr^.typ = reellzahlknoten ) THEN
ganzzahlig := lizgr^.typ = ganzzahlknoten;
IF baum^.funktion # quadrat THEN
ganzzahlig := FALSE
END (* IF *);
codegen ( optcode , baum );
wert := funktion ( optcode );
IF ok THEN
baum := loescherechts ( baum );
IF ganzzahlig AND ( ABS ( wert ) < 32000. ) THEN
baum^.typ := ganzzahlknoten;
IF wert > 0. THEN
baum^.ganzzahl := TRUNC ( wert + 0.5 )
ELSE
baum^.ganzzahl := TRUNC ( wert - 0.5 )
END (* IF *)
ELSE
baum^.typ := reellzahlknoten;
baum^.reellzahl := wert
END (* IF *)
END (* IF *)
END (* IF *)
END (* IF *)
END konstausdruck;
BEGIN (* von optimiere2 *)
IF baum # NIL THEN
optimiere2 ( baum^.links );
optimiere2 ( baum^.rechts );
konstausdruck ( baum );
IF ok AND ( baum^.typ = operationsknoten ) THEN
lizgr := baum^.links;
rezgr := baum^.rechts;
IF lizgr^.typ = ganzzahlknoten THEN
CASE baum^.operation OF
plus : IF lizgr^.ganzzahl = 0 THEN
baum := loeschelinks ( baum )
END (* IF *)
| mal : CASE lizgr^.ganzzahl OF
-1 : lizgr^.ganzzahl := 0;
baum^.operation := minus;
| 0 : baum := loescherechts ( baum )
| 1 : baum := loeschelinks ( baum )
ELSE
END (* CASE *)
| durch : IF lizgr^.ganzzahl = 0 THEN
baum := loescherechts ( baum )
END (* IF *)
| hoch : IF ( lizgr^.ganzzahl = 0 ) OR
( lizgr^.ganzzahl = 1 ) THEN
baum := loescherechts ( baum )
END (* IF *)
ELSE
END (* CASE *)
ELSIF rezgr^.typ = ganzzahlknoten THEN
CASE baum^.operation OF
plus , minus :
IF rezgr^.ganzzahl = 0 THEN
baum := loescherechts ( baum )
END (* IF *)
| mal :
CASE rezgr^.ganzzahl OF
-1 : rezgr^.ganzzahl := 0;
baum^.operation := minus;
baum^.links := rezgr;
baum^.rechts := lizgr
| 0 : baum := loeschelinks ( baum )
| 1 : baum := loescherechts ( baum )
ELSE
END (* CASE *)
| durch :
IF rezgr^.ganzzahl = 1 THEN
baum := loescherechts ( baum );
ELSIF rezgr^.ganzzahl = -1 THEN
rezgr^.ganzzahl := 0;
baum^.operation := minus;
baum^.links := rezgr;
baum^.rechts := lizgr
END (* IF *)
| hoch :
CASE rezgr^.ganzzahl OF
-1 : rezgr^.ganzzahl := 1;
baum^.operation := durch;
baum^.links := rezgr;
baum^.rechts := lizgr
| 0 : baum := loeschelinks ( baum );
baum^.ganzzahl := 1
| 1 : baum := loescherechts ( baum )
ELSE
END (* CASE *)
END (* CASE *)
END (* IF *)
ELSE
ok := TRUE
END (* IF *)
END (* IF *)
END optimiere2;
BEGIN (* von optimiere *)
codeanf ( optcode );
ok := TRUE;
optimiere2 ( baum );
codeloe ( optcode )
END optimiere;
BEGIN (* von analyse *)
fnamen [sinush ] := 'SINH ';
fnamen [cosinush ] := 'COSH ';
fnamen [tangensh ] := 'TANH ';
fnamen [cotangensh ] := 'COTH ';
fnamen [arsinush ] := 'ARSINH ';
fnamen [arcosinush ] := 'ARCOSH ';
fnamen [artangensh ] := 'ARTANH ';
fnamen [arcotangensh] := 'ARCOTH ';
fnamen [sinus ] := 'SIN ';
fnamen [cosinus ] := 'COS ';
fnamen [tangens ] := 'TAN ';
fnamen [cotangens ] := 'COT ';
fnamen [arcsinus ] := 'ARCSIN ';
fnamen [arccosinus ] := 'ARCCOS ';
fnamen [arctangens ] := 'ARCTAN ';
fnamen [arccotangens] := 'ARCCOT ';
fnamen [ehoch ] := 'EXP ';
fnamen [lne ] := 'LN ';
fnamen [lg ] := 'LOG ';
fnamen [pot10 ] := 'POT10 ';
fnamen [wurzel ] := 'WRZL ';
fnamen [quadrat ] := 'QUAD ';
serverseg := LoadSeg ( ADR ( "devs:server" ) );
Assert ( serverseg # NIL , ADR ( "Server läßt sich nicht laden" ) );
serverproc := CreateProc ( ADR ( "server" ) , 0 , serverseg , 1024 );
Assert ( serverproc # NIL , ADR ( "serverproc nicht startbar." ) );
replyportptr := CreatePort ( NIL , 0 );
startupmsg.startupkopf.replyPort := replyportptr;
startupmsg.startupkopf.length := 1;
startupmsg.errorflg := CHAR ( 0 );
kommandomsg.kommandokopf.replyPort := replyportptr;
kommandomsg.kommandokopf.length := 26;
startupmsg.kportadr := ADR ( varfeld );
PutMsg ( serverproc , ADR ( startupmsg ) );
WaitPort ( replyportptr );
dummy := GetMsg ( replyportptr );
Assert ( startupmsg.errorflg = CHAR ( 0 ) , ADR ( "Lib. geht nicht auf." ) );
kommandoport := startupmsg.kportadr;
TermProcedure ( shootdownserver )
END analyse.